<!--
/**
 * XenPageLayout 通用页面布局组件
 * 
 * 功能：
 * - 集成导航栏、内容区、加载状态等完整页面结构
 * - 提供丰富的插槽系统，满足不同页面的灵活需求
 * - 支持下拉刷新、加载更多、错误状态等常见页面状态
 * - 内置安全区域适配，兼容各种设备尺寸
 * 
 * 使用方式：
 * <XenPageLayout
 *   title="页面标题"
 *   :loading="isLoading"
 *   :error="hasError"
 *   :enablePullRefresh="true"
 *   @refresh="onRefresh"
 *   @retry="onRetry"
 * >
 * </XenPageLayout>
 * 
 * Props 说明:
 * - loading: 是否显示加载状态 (Boolean, 默认: false)
 * - error: 是否显示错误状态 (Boolean, 默认: false)
 * - title: 页面标题 (String, 默认: "")
 * - showNavbar: 是否显示导航栏 (Boolean, 默认: true)
 * - showBack: 是否显示返回按钮 (Boolean, 默认: true)
 * - titleAlign: 标题对齐方式 (String, 默认: "center")
 * - navbarBgColor: 导航栏背景色 (String, 默认: "#FFFFFF")
 * - navbarTextColor: 导航栏文字颜色 (String, 默认: "#000000")
 * - navbarBorder: 是否显示导航栏底部边框 (Boolean, 默认: true)
 * - navbarFixed: 导航栏是否固定 (Boolean, 默认: true)
 * - navbarHeight: 导航栏高度 (Number, 默认: 44)
 * - navbarZIndex: 导航栏z-index (Number, 默认: 100)
 * - contentClass: 内容区域自定义类名 (String/Array/Object, 默认: "")
 * - contentStyle: 内容区域自定义样式 (String/Object, 默认: "")
 * - paddingTop: 内容区域顶部内边距 (String/Number, 默认: "")
 * - paddingBottom: 内容区域底部内边距 (String/Number, 默认: "")
 * - enablePullRefresh: 是否启用下拉刷新 (Boolean, 默认: false)
 * - pullText: 下拉刷新提示文本 (String, 默认: "下拉刷新")
 * - refreshingText: 刷新中提示文本 (String, 默认: "刷新中...")
 * - enableLoadMore: 是否启用加载更多 (Boolean, 默认: false)
 * - hasMore: 是否还有更多数据 (Boolean, 默认: true)
 * - loadMoreText: 加载更多提示文本 (String, 默认: "加载更多...")
 * - noMoreText: 没有更多数据提示文本 (String, 默认: "没有更多数据了")
 * - errorText: 错误提示文本 (String, 默认: "加载失败，请重试")
 * - retryText: 重试按钮文本 (String, 默认: "重新加载")
 * - loadingText: 加载中提示文本 (String, 默认: "加载中...")
 * - theme: 主题 (String, 默认: "light", 可选: "light", "dark")
 * - useSafeArea: 是否适配顶部安全区域 (Boolean, 默认: true)
 * - useSafeAreaBottom: 是否适配底部安全区域 (Boolean, 默认: true)
 * - fabPosition: 悬浮按钮位置 (String, 默认: "bottom-right", 可选: "top-left", "top-right", "bottom-left", "bottom-right")
 * 
 * 事件:
 * - @back: 点击返回按钮触发
 * - @retry: 点击重试按钮触发
 * - @refresh: 下拉刷新触发
 * - @loadMore: 加载更多触发
 * - @scroll: 内容区域滚动触发
 */
-->
<template>
  <view
    class="xen-page"
    :class="[theme, { 'xen-page--safe-area': useSafeArea && isH5 }]"
  >
    <!-- 导航栏 -->
    <XenNavbar
      v-if="showNavbar"
      :title="title"
      :show-back="showBack"
      :title-align="titleAlign"
      :background-color="navbarBgColor"
      :color="navbarTextColor"
      :border="navbarBorder"
      :fixed="navbarFixed"
      :height="navbarHeight"
      :z-index="navbarZIndex"
      :navbar-icon-color="navbarIconColor"
      :safe-area-inset-top="useSafeArea"
      @back="onNavBack"
      @height-change="onNavbarHeightChange"
    >
      <!-- 导航栏左侧插槽 -->
      <template #left>
        <slot name="left">
          <view
            v-if="showBack"
            class="xen-navbar__back-btn"
            @click="handleBack"
          >
            <uni-icons
              type="left"
              size="24"
              :color="navbarIconColor"
            ></uni-icons>
            <text v-if="backText" class="xen-navbar__back-text">{{
              backText
            }}</text>
          </view>
        </slot>
      </template>

      <!-- 导航栏中间插槽 -->
      <template #center>
        <slot name="center">
          <view class="xen-navbar__title-container">
            <text class="xen-navbar__title" :style="titleTextStyle">{{
              title
            }}</text>
          </view>
        </slot>
      </template>

      <!-- 导航栏右侧插槽 -->
      <template #right>
        <slot name="right"></slot>
      </template>
    </XenNavbar>

    <!-- 自定义导航栏下的搜索栏或标签栏 -->
    <view class="xen-page__sub-header" v-if="$slots.subHeader">
      <slot name="subHeader"></slot>
    </view>

    <!-- 内容区域 -->
    <view
      class="xen-page__content"
      :class="contentClass"
      :style="[contentStyle, platformContentStyle]"
      @scroll="onScroll"
    >
      <!-- 下拉刷新区域 -->
      <view v-if="enablePullRefresh" class="xen-page__refresh">
        <slot name="refresh">
          <view
            class="xen-page__refresh-indicator"
            :class="{ refreshing: isRefreshing }"
          >
            <text>{{ isRefreshing ? refreshingText : pullText }}</text>
          </view>
        </slot>
      </view>

      <!-- 加载中提示 -->
      <view v-if="loading" class="xen-page__loading">
        <slot name="loading">
          <view class="xen-page__loading-spinner"></view>
          <text>{{ loadingText }}</text>
        </slot>
      </view>

      <!-- 主要内容 -->
      <view v-else-if="!error">
        <!-- 顶部内容插槽 -->
        <view class="xen-page__header" v-if="$slots.header">
          <slot name="header"></slot>
        </view>

        <!-- 主体内容插槽 -->
        <slot></slot>

        <!-- 底部内容区域 -->
        <view class="xen-page__body-footer" v-if="$slots.bodyFooter">
          <slot name="bodyFooter"></slot>
        </view>

        <!-- 加载更多区域 -->
        <view v-if="enableLoadMore" class="xen-page__load-more">
          <slot name="loadMore">
            <view class="xen-page__load-more-text">
              <text v-if="hasMore">{{ loadMoreText }}</text>
              <text v-else>{{ noMoreText }}</text>
            </view>
          </slot>
        </view>
      </view>

      <!-- 错误提示 -->
      <view v-else class="xen-page__error">
        <slot name="error">
          <view class="xen-page__error-content">
            <text class="xen-page__error-text">{{ errorText }}</text>
            <button class="xen-page__error-btn" @click="onRetry">
              {{ retryText }}
            </button>
          </view>
        </slot>
      </view>
    </view>

    <!-- 悬浮按钮 -->
    <view v-if="$slots.fab" class="xen-page__fab" :class="fabPosition">
      <slot name="fab"></slot>
    </view>

    <!-- 底部固定区域 -->
    <view
      v-if="$slots.footer"
      class="xen-page__footer"
      :class="{ 'xen-page__footer--safe-area': useSafeAreaBottom && isH5 }"
    >
      <slot name="footer"></slot>
    </view>

    <!-- 弹出层 -->
    <slot name="popup"></slot>
  </view>
</template>

<script setup lang="ts">
import { ref, onMounted, computed } from "vue";
import XenNavbar from "@/components/XenNavbar.vue";

// 定义组件名称
defineOptions({
  name: "XenPageLayout",
});

// 定义属性
const props = withDefaults(
  defineProps<{
    // 页面状态
    loading?: boolean;
    error?: boolean;

    // 导航栏配置
    title?: string;
    showNavbar?: boolean;
    showBack?: boolean;
    titleAlign?: string;
    navbarBgColor?: string;
    navbarTextColor?: string;
    navbarBorder?: boolean;
    navbarFixed?: boolean;
    navbarHeight?: number;
    navbarZIndex?: number;
    navbarIconColor?: string;

    // 内容区域配置
    contentClass?: string | string[] | Record<string, boolean>;
    contentStyle?: string | Record<string, string>;
    paddingTop?: string | number;
    paddingBottom?: string | number;

    // 下拉刷新配置
    enablePullRefresh?: boolean;
    pullText?: string;
    refreshingText?: string;

    // 加载更多配置
    enableLoadMore?: boolean;
    hasMore?: boolean;
    loadMoreText?: string;
    noMoreText?: string;

    // 错误状态配置
    errorText?: string;
    retryText?: string;

    // 加载中文本
    loadingText?: string;

    // 主题配置
    theme?: string;

    // 安全区域配置
    useSafeArea?: boolean;
    useSafeAreaBottom?: boolean;

    // 悬浮按钮位置
    fabPosition?: string;

    // 新增属性
    backText?: string;
    titleTextStyle?: object;
  }>(),
  {
    loading: false,
    error: false,
    title: "",
    showNavbar: true,
    showBack: true,
    titleAlign: "center",
    navbarBgColor: "#FFFFFF",
    navbarTextColor: "#000000",
    navbarIconColor: "#000000",
    navbarBorder: false,
    navbarFixed: true,
    navbarHeight: 44,
    navbarZIndex: 100,
    contentClass: "",
    contentStyle: "",
    paddingTop: "",
    paddingBottom: "",
    enablePullRefresh: false,
    pullText: "下拉刷新",
    refreshingText: "刷新中...",
    enableLoadMore: false,
    hasMore: true,
    loadMoreText: "加载更多...",
    noMoreText: "没有更多数据了",
    errorText: "加载失败，请重试",
    retryText: "重新加载",
    loadingText: "加载中...",
    theme: "light",
    useSafeArea: true,
    useSafeAreaBottom: true,
    fabPosition: "bottom-right",
    backText: "",
    titleTextStyle: () => ({}),
  },
);

// 定义事件
const emit = defineEmits<{
  (e: "back"): void;
  (e: "retry"): void;
  (e: "refresh"): void;
  (e: "loadMore"): void;
  (e: "scroll", event: any): void;
}>();

const isRefreshing = ref(false);
const navbarActualHeight = ref(0);
const isH5 = ref(false);

// 初始化
onMounted(() => {
  // #ifdef H5
  isH5.value = true;
  // #endif
});

// 导航栏高度变化处理
const onNavbarHeightChange = (height: number) => {
  navbarActualHeight.value = height;
};

// 计算标题文本样式
const titleTextStyle = computed(() => {
  return {
    color: props.navbarTextColor,
    ...props.titleTextStyle,
  };
});

// 导航栏返回按钮点击事件
const onNavBack = () => {
  emit("back");
};

// 错误状态下重试按钮点击事件
const onRetry = () => {
  emit("retry");
};

// 模拟下拉刷新
const startRefresh = () => {
  if (props.enablePullRefresh && !isRefreshing.value) {
    isRefreshing.value = true;
    emit("refresh");

    // 模拟刷新完成
    setTimeout(() => {
      isRefreshing.value = false;
    }, 2000);
  }
};

// 内容滚动事件
const onScroll = (e: any) => {
  emit("scroll", e);
};

// 返回上一页方法
const handleBack = () => {
  uni.navigateBack({
    delta: 1,
    fail: () => {
      // 如果无法返回上一页，则回到首页
      uni.switchTab({
        url: "/pages/work/work",
        fail: () => {
          console.error("返回首页失败");
        },
      });
    },
  });
};

// 计算平台相关的内容样式
const platformContentStyle = computed(() => {
  return {};
});
</script>

<style lang="scss">
/* 页面容器 */
.xen-page {
  display: flex;
  flex-direction: column;
  background-color: #ffffff;
  box-sizing: border-box;
  overflow: hidden;

  /* 亮色主题 */
  &.light {
    --xen-page-bg-color: #ffffff;
    --xen-page-text-color: #333333;
    --xen-page-border-color: #eeeeee;
  }

  /* 暗色主题 */
  &.dark {
    --xen-page-bg-color: #121212;
    --xen-page-text-color: #ffffff;
    --xen-page-border-color: #333333;

    background-color: #121212;
    color: #ffffff;
  }

  /* 顶部安全区域适配（仅H5） */
  &--safe-area {
    /* #ifdef H5 */
    padding-top: constant(safe-area-inset-top); /* iOS 11.0 */
    padding-top: env(safe-area-inset-top); /* iOS 11.2+ */
    /* #endif */
  }

  /* 内容区域 */
  &__content {
    flex: 1;
    position: relative;
    box-sizing: border-box;
    overflow-y: auto;
    padding: 0 5px;
  }

  /* 头部区域 */
  &__header {
    width: 100%;
  }

  /* 子头部区域（导航栏下方） */
  &__sub-header {
    width: 100%;
    z-index: 99;
  }

  /* 下拉刷新区域 */
  &__refresh {
    width: 100%;
    height: 50px;
    display: flex;
    justify-content: center;
    align-items: center;

    &-indicator {
      text-align: center;
      color: #999;

      &.refreshing {
        color: #2979ff;
      }
    }
  }

  /* 加载中状态 */
  &__loading {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 30px;
    color: #999;

    &-spinner {
      width: 24px;
      height: 24px;
      border: 2px solid #999;
      border-top-color: transparent;
      border-radius: 50%;
      animation: xen-spin 0.8s linear infinite;
      margin-bottom: 10px;
    }
  }

  /* 错误状态 */
  &__error {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    padding: 40px 20px;

    &-content {
      text-align: center;
    }

    &-text {
      color: #999;
      margin-bottom: 15px;
      display: block;
    }

    &-btn {
      background-color: #2979ff;
      color: #fff;
      border: none;
      border-radius: 4px;
      padding: 6px 12px;
      font-size: 14px;
    }
  }

  /* 加载更多区域 */
  &__load-more {
    width: 100%;
    padding: 15px 0;
    text-align: center;

    &-text {
      color: #999;
      font-size: 14px;
    }
  }

  /* 悬浮按钮 */
  &__fab {
    position: fixed;
    z-index: 99;

    &.top-left {
      top: 100px;
      left: 20px;
    }

    &.top-right {
      top: 100px;
      right: 20px;
    }

    &.bottom-left {
      bottom: 20px;
      left: 20px;
    }

    &.bottom-right {
      bottom: 20px;
      right: 20px;
    }
  }

  /* 底部固定区域 */
  &__footer {
    width: 100%;
    background-color: var(--xen-page-bg-color);
    border-top: 1px solid var(--xen-page-border-color);
    z-index: 98;

    /* 底部安全区域适配（仅H5） */
    &--safe-area {
      /* #ifdef H5 */
      padding-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */
      padding-bottom: env(safe-area-inset-bottom); /* iOS 11.2+ */
      /* #endif */
    }
  }

  /* 内容底部区域 */
  &__body-footer {
    margin-bottom: 10px;
  }
}

/* 旋转动画 */
@keyframes xen-spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
.xen-page__loading {
  height: 100vh;
  padding: 0 !important;
}
</style>
